package tech.wenxu.ssoprovider.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.wenxu.ssoprovider.mapper.UserMapper;
import tech.wenxu.ssoprovider.pojo.User;
import tech.wenxu.ssoprovider.service.UserService;
import tech.wenxu.ssoprovider.service.ex.ServiceException;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author zhaowenxu
 * @date 2020/4/13 15:26
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static Map<Integer, String> paramTypeMap = new HashMap<Integer, String>() {
        {
            put(1, "username");
            put(2, "phone");
            put(3, "email");
        }
    };

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private Validator validator;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public int check(String param, Integer type) {
        int resultCount = userMapper.check(paramTypeMap.get(type), param);
        if (resultCount == 0) {
            return resultCount;
        }
        throw new ServiceException(paramTypeMap.get(type) + "当前数据重复");
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public int addUser(User user) {
        // 参数验证
        Set<ConstraintViolation<User>> validate = validator.validate(user);
        if (!validate.isEmpty()) {
            validate.forEach(e -> {
                throw new ServiceException(e.getMessage());
            });
        }
        // 验证数据是否重复
        for (int i = 1; i < 4; i++) {
            String param = i == 1 ? user.getUsername() : (i == 2 ? user.getPhone() : user.getEmail());
            check(param, i);
        }
        // 密码加密
        user.setPassword(DigestUtils.md5Hex(user.getPassword()));
        user.addObject();
        return userMapper.insert(user);
    }

    @Override
    public String login(String username, String password) {
        password = DigestUtils.md5Hex(password);
        User user = userMapper.selectOne(
                new QueryWrapper<User>().lambda()
                    .eq(User::getUsername, username)
                    .eq(User::getPassword, password));
        if (user == null) {
            throw new ServiceException("用户名或密码不正确");
        }
        // 返回ticket
        String ticket = DigestUtils.md5Hex("TICKET_" + System.currentTimeMillis() + username);
        String userJsonString;
        try {
            userJsonString = objectMapper.writeValueAsString(user);
        } catch (JsonProcessingException e) {
            log.error("login方法json格式化错误{}", JSON.toJSONString(user, true));
            throw new ServiceException("login方法json格式化错误{}" + JSON.toJSONString(user, true));
        }
        // 登录成功后将登录信息存入redis中
        stringRedisTemplate.opsForValue().set(ticket, userJsonString, 60 * 60 * 24 * 7);
        return ticket;
    }

    @Override
    public User queryUser(String ticket) {
        String userJsonString = stringRedisTemplate.opsForValue().get(ticket);
        if (StringUtils.isNotBlank(userJsonString)) {
            try {
                return objectMapper.readValue(userJsonString, User.class);
            } catch (Exception e) {
                return JSON.parseObject(userJsonString, User.class);
            }
        } else {
            throw new ServiceException("未查询到当前的用户信息,可能ticket已过期,请重新登录");
        }
    }
}
